//--------------------------------------------------------------------------------------------
//  : 
//      Component name  : fpadd_stage2
//      Author          : 
//      Company         : 
//
//      Description     : 
//
//
//--------------------------------------------------------------------------------------------


module FPadd_stage2(ADD_SUB_out, A_EXP, A_SIGN, A_in, A_isINF, A_isNaN, A_isZ, B_EXP, B_XSIGN, B_in, B_isINF, B_isNaN, B_isZ, EXP_diff, cin_sub, clk, A_SIGN_stage2, A_align, B_XSIGN_stage2, B_align, EXP_base_stage2, cin, invert_A, invert_B, isINF_tab_stage2, isNaN_stage2, isZ_tab_stage2);
   input         ADD_SUB_out;
   input [7:0]   A_EXP;
   input         A_SIGN;
   input [28:0]  A_in;
   input         A_isINF;
   input         A_isNaN;
   input         A_isZ;
   input [7:0]   B_EXP;
   input         B_XSIGN;
   input [28:0]  B_in;
   input         B_isINF;
   input         B_isNaN;
   input         B_isZ;
   input [8:0]   EXP_diff;
   input         cin_sub;
   input         clk;
   output        A_SIGN_stage2;
   reg           A_SIGN_stage2;
   output [28:0] A_align;
   reg [28:0]    A_align;
   output        B_XSIGN_stage2;
   reg           B_XSIGN_stage2;
   output [28:0] B_align;
   reg [28:0]    B_align;
   output [7:0]  EXP_base_stage2;
   reg [7:0]     EXP_base_stage2;
   output        cin;
   reg           cin;
   output        invert_A;
   reg           invert_A;
   output        invert_B;
   reg           invert_B;
   output        isINF_tab_stage2;
   reg           isINF_tab_stage2;
   output        isNaN_stage2;
   reg           isNaN_stage2;
   output        isZ_tab_stage2;
   reg           isZ_tab_stage2;
   
   
   wire [28:0]   A_CS;
   wire [28:0]   A_align_int;
   wire [28:0]   B_CS;
   wire [28:0]   B_align_int;
   reg [7:0]     EXP_base_int;
   wire          cin_int;
   wire [8:0]    diff;
   reg           invert_A_int;
   reg           invert_B_int;
   reg           isINF_tab_int;
   reg           isNaN_int;
   reg           isZ_tab_int;
   wire          swap_AB;
   
   wire [7:0]    mw_I2din0;
   wire [7:0]    mw_I2din1;
   
   
   always @(posedge clk)
      
      begin
         cin <= cin_int;
         invert_A <= invert_A_int;
         invert_B <= invert_B_int;
         EXP_base_stage2 <= EXP_base_int;
         A_align <= A_align_int;
         B_align <= B_align_int;
         A_SIGN_stage2 <= A_SIGN;
         B_XSIGN_stage2 <= B_XSIGN;
         isINF_tab_stage2 <= isINF_tab_int;
         isNaN_stage2 <= isNaN_int;
         isZ_tab_stage2 <= isZ_tab_int;
      end
   
   assign swap_AB = EXP_diff[8];
   assign diff = EXP_diff[8:0];
   
   
   always @(A_SIGN or B_XSIGN or swap_AB)
   begin: InvertLogic_truth_process
      if ((A_SIGN == 1'b0) & (B_XSIGN == 1'b0))
      begin
         invert_A_int = 1'b0;
         invert_B_int = 1'b0;
      end
      else if ((A_SIGN == 1'b1) & (B_XSIGN == 1'b1))
      begin
         invert_A_int = 1'b0;
         invert_B_int = 1'b0;
      end
      else if ((A_SIGN == 1'b0) & (B_XSIGN == 1'b1) & (swap_AB == 1'b0))
      begin
         invert_A_int = 1'b0;
         invert_B_int = 1'b1;
      end
      else if ((A_SIGN == 1'b0) & (B_XSIGN == 1'b1) & (swap_AB == 1'b1))
      begin
         invert_A_int = 1'b1;
         invert_B_int = 1'b0;
      end
      else if ((A_SIGN == 1'b1) & (B_XSIGN == 1'b0) & (swap_AB == 1'b0))
      begin
         invert_A_int = 1'b1;
         invert_B_int = 1'b0;
      end
      else if ((A_SIGN == 1'b1) & (B_XSIGN == 1'b0) & (swap_AB == 1'b1))
      begin
         invert_A_int = 1'b0;
         invert_B_int = 1'b1;
      end
      else
      begin
         invert_A_int = 1'b0;
         invert_B_int = 1'b0;
      end
   end
   
   
   always @(ADD_SUB_out or A_isINF or A_isNaN or A_isZ or B_isINF or B_isNaN or B_isZ)
   begin: exceptions_truth_process
      if (A_isNaN == 1'b1)
      begin
         isINF_tab_int = 1'b0;
         isNaN_int = 1'b1;
         isZ_tab_int = 1'b0;
      end
      else if (B_isNaN == 1'b1)
      begin
         isINF_tab_int = 1'b0;
         isNaN_int = 1'b1;
         isZ_tab_int = 1'b0;
      end
      else if ((ADD_SUB_out == 1'b1) & (A_isINF == 1'b1) & (B_isINF == 1'b1))
      begin
         isINF_tab_int = 1'b1;
         isNaN_int = 1'b0;
         isZ_tab_int = 1'b0;
      end
      else if ((ADD_SUB_out == 1'b0) & (A_isINF == 1'b1) & (B_isINF == 1'b1))
      begin
         isINF_tab_int = 1'b0;
         isNaN_int = 1'b1;
         isZ_tab_int = 1'b0;
      end
      else if (A_isINF == 1'b1)
      begin
         isINF_tab_int = 1'b1;
         isNaN_int = 1'b0;
         isZ_tab_int = 1'b0;
      end
      else if (B_isINF == 1'b1)
      begin
         isINF_tab_int = 1'b1;
         isNaN_int = 1'b0;
         isZ_tab_int = 1'b0;
      end
      else if ((A_isZ == 1'b1) & (B_isZ == 1'b1))
      begin
         isINF_tab_int = 1'b0;
         isNaN_int = 1'b0;
         isZ_tab_int = 1'b1;
      end
      else
      begin
         isINF_tab_int = 1'b0;
         isNaN_int = 1'b0;
         isZ_tab_int = 1'b0;
      end
   end
   
   
   always @(mw_I2din0 or mw_I2din1 or swap_AB)
   begin: I2combo
      reg [7:0]     dtemp;
      case (swap_AB)
         1'b0:
            dtemp = mw_I2din0;
         1'b1:
            dtemp = mw_I2din1;
         default :
            dtemp = {8{1'bX}};
      endcase
      EXP_base_int <= dtemp;
   end
   assign mw_I2din0 = A_EXP;
   assign mw_I2din1 = B_EXP;
   
   assign cin_int = invert_B_int | invert_A_int;
   
   
   FPalign I4(.A_in(A_CS), .B_in(B_CS), .cin(cin_sub), .diff(diff), .A_out(A_align_int), .B_out(B_align_int));
   
   FPswap #(.width(29)) I3(.A_in(A_in), .B_in(B_in), .swap_AB(swap_AB), .A_out(A_CS), .B_out(B_CS));
   
endmodule
